package com.dispacher.context;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.dispacher.log.LogFactory;
import com.dispacher.log.Logger;
import com.dispacher.util.ClassUtil;
import com.dispacher.util.MethodUtil;

public class ContextHolder {

	private static Logger log = LogFactory.getDefaultLog();

	private static ThreadLocal<ContextHolder> localThis = new ThreadLocal<ContextHolder>();

	private HttpServletRequest request;

	private HttpServletResponse response;

	private ContextHolder() {
	}

	/**
	 * 获取上下文保持器
	 * 
	 * @return
	 */
	public static ContextHolder findInstance() {
		ContextHolder result = localThis.get();
		if (result == null) {
			result = new ContextHolder();
			localThis.set(result);
		}
		return result;
	}

	public HttpServletRequest getRequest() {
		return request;
	}

	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	public HttpServletResponse getResponse() {
		return response;
	}

	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}

	public static HttpSession getCurSession() {
		return findInstance().getRequest().getSession();
	}

	/**
	 * 向request中写入信息
	 * 
	 * @param key
	 * @param value
	 */
	public void setReqeustAttr(String key, Object value) {
		getRequest().setAttribute(key, value);
	}

	/**
	 * 向当前线程的request中注入相应的对象的方法
	 * 
	 * @param key
	 * @param value
	 */
	public static void setRequestAttribute(String key, Object value) {
		ContextHolder holder = findInstance();
		holder.getRequest().setAttribute(key, value);
	}

	/**
	 * 将最终的结果分发给相应的jsp的方法
	 * 
	 * @param url
	 */
	public void dispatcherUrl(String url) {
		RequestDispatcher dispatcher = getRequest().getRequestDispatcher(url);
		try {
			dispatcher.forward(getRequest(), getResponse());
		} catch (ServletException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用response进行分发的方法
	 * 
	 * @param url
	 */
	public void dispatcherResponse(String url) {
		try {
			getResponse().sendRedirect(url);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public String getRequestUrl() {
		String result = getRequest().getRequestURI();
		result = result.substring(getContextUri().length() + 1, result.indexOf("."));
		log.log(" the url that request is : " + result);
		return result;
	}

	public String getContextUri() {
		return getRequest().getContextPath();
	}

	/**
	 * 从request对象中实例化出一个对象,可以通过namespace进行实例的初始化
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T initFromTheRequest(String nameSpace, Class<T> cla) {
		Field[] fields = cla.getDeclaredFields();
		Object instance = ClassUtil.findInstance(cla.getName());
		HttpServletRequest request = ContextHolder.findInstance().getRequest();
		boolean isJson = false;
		// determin the data flow, add support for json
		Map<String, String> paramMap = initRequestParamMap(request);

		if (paramMap == null || paramMap.size() == 0) {
			isJson = true;
			paramMap = new HashMap<String, String>();
			String readLine;
			try {
				readLine = new BufferedReader(new InputStreamReader(request.getInputStream(), "utf-8")).readLine();
				if (readLine == null) {
					return null;
				}
				readLine = readLine.trim();
				readLine = readLine.substring(1, readLine.length() - 1);
				String[] strs = readLine.split(",");
				for (String str : strs) {
					String key = str.substring(0, str.indexOf(":")).trim();
					key = key.substring(1, key.length() - 1);
					String value = str.substring(str.indexOf(":") + 1).trim();
					value = value.substring(1, value.length() - 1);
					paramMap.put(key, value);
				}
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		for (Field field : fields) {
			String paramKey = nameSpace + "." + field.getName();
			Object[] params = { (isJson) ? paramMap.get(paramKey) : request.getParameter(paramKey) };
			if (params[0] == null || params[0].equals("")) {
				continue;
			}
			try {
				String method = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
				MethodUtil.invoke(method, instance, params);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			}
		}
		return (T) instance;
	}

	private static Map<String, String> initRequestParamMap(HttpServletRequest request) {
		Map<String, String> paramMap = new HashMap<String, String>();
		Map<String, Object> _paramMap = request.getParameterMap();
		if (_paramMap.isEmpty()) {
			return paramMap;
		}
		for (Entry<String, Object> entry : _paramMap.entrySet()) {
			Object value = entry.getValue();
			if (value.getClass().isArray()) {
				String[] _v = (String[]) value;
				paramMap.put(entry.getKey(), _v[0]);
			}
		}
		return paramMap;
	}

	/**
	 * 从request对象中实例化出一个对象
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T initFromTheRequest(Class<T> cla) {
		Field[] fields = cla.getDeclaredFields();
		Object instance = ClassUtil.findInstance(cla.getName());
		HttpServletRequest request = ContextHolder.findInstance().getRequest();
		boolean isJson = false;
		// determin the data flow, add support for json
		//Map<String, String> paramMap = request.getParameterMap();
		Map<String, String> paramMap = initRequestParamMap(request);
		
		if (paramMap == null || paramMap.size() == 0) {
			isJson = true;
			paramMap = new HashMap<String, String>();
			String readLine;
			try {
				readLine = new BufferedReader(new InputStreamReader(request.getInputStream(), "utf-8")).readLine();
				if (readLine == null) {
					return null;
				}
				readLine = readLine.trim();
				readLine = readLine.substring(1, readLine.length() - 1);
				String[] strs = readLine.split(",");
				for (String str : strs) {
					String key = str.substring(0, str.indexOf(":")).trim();
					key = key.substring(1, key.length() - 1);
					String value = str.substring(str.indexOf(":") + 1).trim();
					value = value.substring(1, value.length() - 1);
					paramMap.put(key, value);
				}
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		for (Field field : fields) {
			Object[] params = { (isJson) ? paramMap.get(field.getName()) : request.getParameter(field.getName()) };
			if (params[0] == null || params[0].equals("")) {
				continue;
			}
			String method = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
			MethodUtil.invoke(method, instance, params);
		}
		return (T) instance;
	}

	/**
	 * 用于向request中获取parameter之后注入到Attributes中
	 * 
	 * @param paramName
	 */
	public static void reinitParameterToRequest(String paramName) {
		String param = findInstance().getRequest().getParameter(paramName);
		findInstance().setReqeustAttr(paramName, param);
	}

	/**
	 * 内部分发方法，将请求转接到某个jsp
	 * 
	 * @param jspUrl
	 */
	public static void forward(String jspUrl) {
		findInstance().dispatcherUrl(jspUrl);
	}

	/**
	 * 将请求进行转发
	 * 
	 * @param url
	 */
	public static void sendRedirect(String url) {
		findInstance().dispatcherResponse(url);
	}

	/**
	 * 用于辅助ajax的一个方法
	 * 
	 * @param content
	 */
	public static void response(String content) {
		HttpServletResponse response = findInstance().getResponse();
		try {
			PrintWriter out = response.getWriter();
			out.write(content);
			out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		String str = "\"key\" : \"d:value\"";
		String key = str.substring(0, str.indexOf(":")).trim();
		key = key.substring(1, key.length() - 1);
		String value = str.substring(str.indexOf(":") + 1).trim();
		value = value.substring(1, value.length() - 1);
		System.out.println(key);
		System.out.println(value);
	}
}
